/*
 * config_packet.h
 *
 *  Created on: 08.07.2013
 *      Author: SpirTanol
 */

#ifndef CONFIG_PACKET_H_
#define CONFIG_PACKET_H_

#include "packets/data_packet.h"
#include "global.h"

class ConfigPacket : public DataPacket
{
	enum Reg
	{
		R_CUR_NOM,
		R_CUR_MIN,
		R_CUR_OVERLOAD,
		R_IMBALANCE_PHASE,
		R_OFF_TIME_DOUBLE_OVERLOAD,
		R_DELAY_START,
		R_AUTO_START,
		R_TEST_PHASES,
		R_FAST_PROTECT,
		R_PROTECT_TIME,
		R_CRASH_PHASES,
		R_RTS_PROTECT,
		R_WETNESS_PROTECT,
		R_RT100_PROTECT,
		R_RT100_TEMP,
		R_VOL_PHASE_MODE,
		R_CICLE_TIMER,
		R_WORK_TIMER,
		R_DELAY_TIMER,
		R_INPUT1_F,
		R_INPUT2_F,
		R_POWER_OUTPUT_F,
		R_APPEND_OUTPUT_F,
		R_SWITCH_DELAY,
		R_REMOTE_CONTROL,

		R_SIZE,
	};

	ushort oData[R_SIZE];

public:
	ConfigPacket() { init(); }
	ConfigPacket(const ConfigPacket *packet);
	~ConfigPacket() {}

	inline void setCurNom(float cur) { oData[R_CUR_NOM] = ushort(cur + 0.5f); }
	inline float curNom() const { return float(oData[R_CUR_NOM]); }
	inline ushort rawCurNom() const { return oData[R_CUR_NOM]; }

	inline void setCurMin(int minCur) { oData[R_CUR_MIN] = ushort(minCur); }
	inline int curMin() const { return int(oData[R_CUR_MIN]); }

	inline void setCurOverload(int curOverload) { oData[R_CUR_OVERLOAD] = ushort(curOverload); }
	inline int curOverload() const { return int(oData[R_CUR_OVERLOAD]); }

	inline void setSwOffPhaseImbalance(int phases) { oData[R_IMBALANCE_PHASE] = ushort(phases); }
	inline int swOffPhaseImbalance() const { return int(oData[R_IMBALANCE_PHASE]); }

	inline void setOffTimeDoubleOverload(int time) { oData[R_OFF_TIME_DOUBLE_OVERLOAD] = ushort(time); }
	inline uint offTimeDoubleOverload() const { return uint(oData[R_OFF_TIME_DOUBLE_OVERLOAD]); }

	inline void setDelayStart(int delay) { oData[R_DELAY_START] = ushort(delay); }
	inline int delayStart() const { return int(oData[R_DELAY_START]); }

	inline void setAutoStart(bool enable) { oData[R_AUTO_START] = (enable ? 1 : 0); }
	inline bool autoStart() const { return (oData[R_AUTO_START] != 0); }

	inline void setTestPhases(bool enable) { oData[R_TEST_PHASES] = (enable ? 1 : 0); }
	inline bool testPhases() const { return (oData[R_TEST_PHASES] != 0); }

	inline void setFastProtect(bool enable) { oData[R_FAST_PROTECT] = (enable ? 1 : 0); }
	inline bool fastProtect() const { return (oData[R_FAST_PROTECT] != 0); }

	/** Время реакции защиты от перегрузки по току */
	inline void setProtectTime(int time) { oData[R_PROTECT_TIME] = ushort(time); }
	/** Время реакции защиты от перегрузки по току */
	inline int protectTime() const { return int(oData[R_PROTECT_TIME]); }

	/** Допустимое количество оборванных фаз */
	inline void setCountCrashPhases(int count) { oData[R_CRASH_PHASES] = ushort(count); }
	/** Допустимое количество оборванных фаз */
	inline int countCrashPhases() const { return int(oData[R_CRASH_PHASES]); }

	inline void setRTSProtect(bool enable) { oData[R_RTS_PROTECT] = (enable ? 1 : 0); }
	inline bool rtsProtect() const { return (oData[R_RTS_PROTECT] != 0); }

	inline void setWetnessProtect(bool enable) { oData[R_WETNESS_PROTECT] = (enable ? 1 : 0); }
	inline bool wetnessProtect() const { return (oData[R_WETNESS_PROTECT] != 0); }

	inline void setRT100Protect(bool enable) { oData[R_RT100_PROTECT] = (enable ? 1 : 0); }
	inline bool rt100Protect() const { return (oData[R_RT100_PROTECT] != 0); }

	/** Порог срабатывания защиты по термодатчику PT100 */
	inline void setRT100Temp(int temp) { oData[R_RT100_TEMP] = ushort(temp); }
	/** Порог срабатывания защиты по термодатчику PT100 */
	inline int rt100temp() const { return int(oData[R_RT100_TEMP]); }

	inline void setVolPhaseMode(int mode) { oData[R_VOL_PHASE_MODE] = ushort(mode); }
	inline int volPhaseMode() const { return int(oData[R_VOL_PHASE_MODE]); }

	inline void setCicleTimer(bool enable) { oData[R_CICLE_TIMER] = (enable ? 1 : 0); }
	inline bool cicleTimer() const { return (oData[R_CICLE_TIMER] != 0); }

	/** Продолжительность работы двигателя при работе в циклическом режиме */
	inline void setWorkTimer(int time) { oData[R_WORK_TIMER] = ushort(time); }
	/** Продолжительность работы двигателя при работе в циклическом режиме */
	inline int workTimer() const { return int(oData[R_WORK_TIMER]); }

	/** Продолжительность простоя двигателя при работе в циклическом режиме */
	inline void setDelayTimer(int delay) { oData[R_DELAY_TIMER] = ushort(delay); }
	/** Продолжительность простоя двигателя при работе в циклическом режиме */
	inline int delayTimer() const { return int(oData[R_DELAY_TIMER]); }

	inline void setInput1F(int f) { oData[R_INPUT1_F] = ushort(f); }
	inline int input1F() const { return int(oData[R_INPUT1_F]); }

	inline void setInput2F(int f) { oData[R_INPUT2_F] = ushort(f); }
	inline int input2F() const { return int(oData[R_INPUT2_F]); }

	inline void setPowerOutputF(int f) { oData[R_POWER_OUTPUT_F] = ushort(f); }
	inline int powerOutputF() const { return int(oData[R_POWER_OUTPUT_F]); }

	inline void setAppendOutputF(int f) { oData[R_APPEND_OUTPUT_F] = ushort(f); }
	inline int appendOutputF() const { return int(oData[R_APPEND_OUTPUT_F]); }

	inline void setSwitchDelay(int delay) { oData[R_SWITCH_DELAY] = ushort(delay); }
	inline int switchDelay() const { return int(oData[R_SWITCH_DELAY]); }

	inline void setRemoteControl(bool enable) { oData[R_REMOTE_CONTROL] = (enable ? 1 : 0); }
	inline bool remoteControl() const { return (oData[R_REMOTE_CONTROL] != 0); }

	inline ConfigPacket *clone() const { return new ConfigPacket(this); } // [virtual]

	virtual int version() const { return 0; }

private:
	inline void init() { addPart(Part(oData, R_SIZE, 5)); }

};

class ConfigPacketV50 : public ConfigPacket
{
	ushort oTimePtotectOfBiasCurrents;

public:
	ConfigPacketV50() : ConfigPacket() { init(); }
	ConfigPacketV50(const ConfigPacketV50 *packet);
	~ConfigPacketV50() {}

	inline void setTimeProtectOfBiasCurrents(uint time) { oTimePtotectOfBiasCurrents = ushort(time); }
	inline uint timeProtectOfBiasCurrents() const { return uint(oTimePtotectOfBiasCurrents); }

	int version() const { return 50; } // [virtual]

	inline ConfigPacketV50 *clone() const { return new ConfigPacketV50(this); } // [virtual]

private:
	inline void init() { addPart(Part(&oTimePtotectOfBiasCurrents, 1, 30)); }

};

class ConfigPacketV70 : public ConfigPacketV50
{
	enum Reg
	{
		R_PROTECTION_THRESHOLD_OF_IDLE,
		R_PROTECTION_THRESHOLD_OF_INSULATION,

		R_SIZE
	};

	ushort oData[R_SIZE];

public:
	ConfigPacketV70() : ConfigPacketV50() { init(); }
	ConfigPacketV70(const ConfigPacketV70 *packet);
	~ConfigPacketV70() {}

	inline void setProtectionThresholdOfIdle(float threshold) { oData[R_PROTECTION_THRESHOLD_OF_IDLE] = ushort(threshold * 10.0f); }
	inline float protectionThresholdOfIdle() const { return float(oData[R_PROTECTION_THRESHOLD_OF_IDLE]) * 0.1f; }

	inline void setProtectionThresholdOfInsulation(int thresholdMode) { oData[R_PROTECTION_THRESHOLD_OF_INSULATION] = ushort(thresholdMode); }
	inline int protectionThresholdOfInsulation() const { return int(oData[R_PROTECTION_THRESHOLD_OF_INSULATION]); }

	int version() const { return 70; } // [virtual]

	inline ConfigPacketV70 *clone() const { return new ConfigPacketV70(this); } // [virtual]

private:
	inline void init() { addPart(Part(oData, R_SIZE, 190)); }

};

#endif /* CONFIG_PACKET_H_ */
